The multiplication puzzle is played
with a row of cards, each containing a single positive integer. During the move
player takes one card out of the row and scores the number of points equal to
the product of the number on the card taken and the numbers on the cards on the
left and on the right of it. It is not allowed to take out the first and the
last card in the row. After the final move, only two cards are left in the row.
The goal is to take cards in such
order as to minimize the total number of scored points.
For example, if cards in the row
contain numbers 10 1 50 20 5, player might take a card with 1, then 20 and 50,
scoring
10*1*50 + 50*20*5 + 10*50*5 = 500 +
5000 + 2500 = 8000
If he would take the cards in the
opposite order, i.e. 50, then 20, then 1, the score would be
1*50*20 + 1*20*5 + 10*1*5 = 1000 +
100 + 50 = 1150
Input. The first
line contains the number of cards n
(3 ≤ n ≤ 100). The second
line contains n integers in the range
from 1 to 100, separated by spaces.
Output. Output
must contain a single integer – the minimal score.
Пример входа |
Пример выхода |
6 10 1 50 50 20 5 |
3650 |
динамическое
программирование
Входную
последовательность карт занесем в массив a[0, …, n – 1]. Пусть f(i, j) – наименьшее количество баллов,
которое можно получить, удалив все карты строго внутри отрезка [ai, …, aj] (кроме крайних двух ai и aj,
крайние карты по условию задачи удалять нельзя). Сохраним это значение в ячейке
dp[i][j]. Тогда ответом на задачу будет f(0, n – 1).
Занесем в
ячейки массива dp значения INF = ∞, инициализируем dp[i][i]
= dp[i][i + 1] = 0.
Предположим,
что при убирании чисел внутри отрезка [ai,
…, aj] последним будет
убрано ak (i < k < j). При этом оно в
общую сумму принесет слагаемое ai
ak aj. Но для того чтобы ak на последнем шаге выбора карты было соседним с ai и aj, необходимо перед этим убрать все карты внутри отрезков
[ai, …, ak] и [ak, …, aj].
То есть
f(i, j)
=
Реализация алгоритма
#include <string.h>
#include <stdio.h>
#define MAX 110
#define INF 0x3F3F3F3F
int dp[MAX][MAX], a[MAX];
int i,j,k,n,g;
int min(int
i, int j)
{
return (i < j) ? i : j;
}
int f(int
i, int j)
{
if (dp[i][j] == INF)
for (int k = i + 1; k
< j; k++)
dp[i][j] =
min(dp[i][j], f(i,k) + f(k,j) + a[i] * a[k] * a[j]);
return dp[i][j];
}
int main(void)
{
scanf("%d",&n);
memset(dp,0x3F,sizeof(dp));
for(i = 0; i < n; i++)
{
scanf("%d",&a[i]);
dp[i][i] = 0;
dp[i][i+1] = 0;
}
printf("%d\n",f(0,n-1));
return 0;
}